#pragma once

// #include <fbjni/fbjni.h>

#include <exception>
#include <functional>
#include <memory>
#include <mutex>
#include <queue>
#include <string>

#include "RNSkPlatformContext.h"

class SkStreamAsset;
namespace RNSkia {
namespace jsi = facebook::jsi;
namespace jni = facebook::jni;

class JniPlatformContext : public jni::HybridClass<JniPlatformContext> {
public:
    static auto constexpr kJavaDescriptor = "Lcom/shopify/reactnative/skia/PlatformContext;";

    static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis, const float);

    static void registerNatives();

    void performStreamOperation(const std::string &sourceUri,
        const std::function<void(std::unique_ptr<SkStreamAsset>)> &op);

    void raiseError(const std::exception &err);

    void startDrawLoop();
    void stopDrawLoop();

    void notifyDrawLoopExternal();

    void notifyTaskReadyExternal();

    void runTaskOnMainThread(std::function<void()> task);

    float getPixelDensity()
    {
        return _pixelDensity;
    }

    sk_sp<SkImage> takeScreenshotFromViewTag(size_t tag);

    void setOnNotifyDrawLoop(const std::function<void(void)> &callback)
    {
        _onNotifyDrawLoop = callback;
    }

    jni::global_ref<jobject> createVideo(const std::string &url);

private:
    friend HybridBase;
    jni::global_ref<JniPlatformContext::javaobject> javaPart_;

    float _pixelDensity;

    std::function<void(void)> _onNotifyDrawLoop;

    std::queue<std::function<void()>> _taskCallbacks;

    std::shared_ptr<std::mutex> _taskMutex;

    explicit JniPlatformContext(jni::alias_ref<JniPlatformContext::jhybridobject> jThis, const float pixelDensity)
        : _taskMutex(std::make_shared<std::mutex>()), javaPart_(jni::make_global(jThis)), _pixelDensity(pixelDensity)
    {}
};
} // namespace RNSkia